package org.hit.burkun.network;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SerializableGraph implements Serializable{
	/**
	 * 将整个图序列化到本地
	 */
	private static final long serialVersionUID = 5660606222303364770L;
	private HashMap<Vertex, LinkedList<EdgeInfo>> edgsMap = new HashMap<>();
	private HashMap<String, Vertex> umls2Nodes;
	
	private static Logger log = LoggerFactory.getLogger(Serializable.class);
	public SerializableGraph(){
		Vertex.initNextCounter();
	}
	public Collection<Vertex> getAllVertexs(){
		return umls2Nodes.values();
	}
	
	public void setAllVertexs(HashMap<String, Vertex> umls2Nodes){
		this.umls2Nodes = umls2Nodes;
	}
	
	public LinkedList<EdgeInfo> getNeighborsByVertex(Vertex v){
		return edgsMap.get(v);
	}
	
	public void addEdge(Vertex v, EdgeInfo edge){
		if(edgsMap.containsKey(v)){
			LinkedList<EdgeInfo> es = edgsMap.get(v);
			//不能融合上去
			if(!mergeEdge(es, edge)){
				es.add(edge);
			}
		}else{
			LinkedList<EdgeInfo> es = new LinkedList<>();
			es.add(edge);
			edgsMap.put(v, es);
		}
	}
	public HashMap<Vertex, LinkedList<EdgeInfo>> getEdgeMap(){
		return edgsMap;
	}
	
	private boolean mergeEdge(LinkedList<EdgeInfo> edges, EdgeInfo edge){
		for(EdgeInfo ee : edges){
			if(ee.getVertex().equals(edge.getVertex())){
				double s1 = ee.getScore();
				double s2= edge.getScore();
				//取最大值融合上去
				ee.setScore(Math.max(s1, s2));
				ee.setRelType(edge.getRelType());
				return true;
			}
		}
		return false;
	}
	
	public Vertex getVertexByUmls(String umls){
		return umls2Nodes.get(umls);
	}
	
	public static void writeObject(File file, Serializable sm) throws IOException {
		log.debug("write object to" + file.getName() + "...");
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
		oos.writeObject(sm);
		oos.close();
	}

	public static Serializable readObject(File file){
		ObjectInputStream ois = null;
		try {
			log.debug("read object from " + file.getName() + "...");
			ois = new ObjectInputStream(new FileInputStream(file));
			return (Serializable) ois.readObject();
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
			return null;
		}finally{
			if(ois != null){
				try {
					ois.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private HashMap<Integer, Vertex> uidToVertex = null;
	private void initInt2Vertex(){
		if(uidToVertex == null){
			uidToVertex = new HashMap<>();
			Collection<Vertex> vs = getAllVertexs();
			for(Vertex v : vs){
				uidToVertex.put(v.getUid(), v);
			}
		}
	}
	public Vertex getVertexByUid(int uid){
		initInt2Vertex();
		return uidToVertex.get(uid);
	}
}
